<?php

namespace app\common\library;

use think\Queue;

class YuUtil
{
    const VERSION = '6.0.5';

    protected $errorString = '';

    public static $instance ;

    /**
     * @title 单例调用
     * @description 单例调用
     * @author Admin ldy
     * @time 2018/9/25  12:22
     */
    public static function getInstance(){
        if (YuUtil::$instance == null){
            YuUtil::$instance = new \app\common\library\YuUtil;
            return YuUtil::$instance;
        }else{
            return YuUtil::$instance;
        }
    }

    public function __construct(){
        //初始化
    }

    /**
     * @title 发送一个消息
     * @description 发送一个异步消息，后台自动执行，不阻塞
     * @author Admin ldy
     * @param name:$jobHandlerClassName  type:string require:1 default:1 desc:执行的任务名字
     * @param name:$jobData  type:array require:1 default:1 desc:消息数据，数组格式
     * @param name:$jobQueueName  type:string require:1 default:1 desc: 消息组名，默认是yuJobQueue
     * @time 2018/9/25  13:48
     * @return mixed:返回是否发送成功
     */
    public static function postMsg($jobHandlerClassName,$jobData,$jobQueueName = "yuJobQueue"){
        $isPushed = Queue::push( $jobHandlerClassName , $jobData , $jobQueueName );
        return $isPushed;
    }

    /**
     * @title 发送消息到队列
     * @description 发送一个异步消息，后台自动执行，不阻塞
     * @author Admin ldy
     * @param name:$jobHandlerClassName  type:string require:1 default:1 desc:任务的名称
     * @param name:$jobData  type:string require:1 default:1 desc:任务需要的数据
     * @param name:$level  type:string require:1 default:1 desc:响应级别，1级最快，2级为普通，3级为最耗时操作
     * @time 2018/11/14  15:12
     * @return mixed
     */
    public static function postMsgByLevel($jobHandlerClassName,$jobData,$level = "1"){
        if ($level=='1'){
            $jobQueueName = 'yuJobQueueFast';
        }else if($level=='2'){
            $jobQueueName = 'yuJobQueue';
        }else if($level=='3'){
            $jobQueueName = 'yuJobQueueTime';
        }else{//其他的级别有待扩展
            $jobQueueName = 'yuJobQueue';
        }
        $isPushed = Queue::push( $jobHandlerClassName , $jobData , $jobQueueName );
        return $isPushed;
    }

    /**
     * @title 在数组中获取一个字符串
     * @description 在数组中获取一个字符串，如果没有该key，则返回空字符串
     * @author Admin ldy
     * @param name:key  type:string require:1 default:1 desc:
     * @param name:array  type:array require:1 default:1 desc:
     * @time 2018/9/20  14:08
     * @return string:返回的字符串
     */
    public static function getStringByKey($key,$array){
        if (isset($array[$key])){
            $re = $array[$key];
        }else{
            $re = '';
        }
        return $re;
    }


    /**
     * @title 将传入的值，加1后返回
     * @description 将传入的值，加1后返回
     * @author Admin ldy
     * @param name:$da  type:string require:1 default:1 desc:
     * @time 2018/9/20  14:18
     * @return int:返回一个整型数据
     */
    public static function addIntValue($da){
        if ($da == null ||empty($da)){
            $da = 1;
        }else{
            $da = $da+1;
        }
        return $da;
    }


    /**
     * @title 异步执行某个URL方法
     * @description 异步执行某个URL方法，不阻塞
     * @author Admin ldy
     * @param name:url  type:string require:1 default:1 desc:
     * @param name:$param
     * @time 2018/9/20  12:29
     */
    public static function asyn_do_post($url, $param=array()){
        $urlinfo = parse_url($url);
        $host = $urlinfo['host'];
        $path = $urlinfo['path'];
        $query = isset($param)? http_build_query($param) : '';
        $port = 80;
        $errno = 0;
        $errstr = '';
        $timeout = 5;
        $fp = fsockopen($host, $port, $errno, $errstr, $timeout);
        if(!$fp){
            echo "$errstr ($errno)<br />\n";
        }
        $out = "POST ".$path." HTTP/1.1\r\n";
        $out .= "host:".$host."\r\n";
        $out .= "content-length:".strlen($query)."\r\n";
        $out .= "content-type:application/x-www-form-urlencoded\r\n";
        $out .= "connection:close\r\n\r\n";
        $out .= $query;

        fputs($fp, $out);
        fclose($fp);
    }

    /**
     * @title 对象转标准数组
     * @description $array对象转标准数组
     * @author Admin ldy
     * @param name:$jsonObject  type:string require:1 default:1 desc: $array对象
     * @time 2018/9/20  16:49
     * @return array
     */
    public static function json_to_array($jsonObject){
        if(is_object($jsonObject)){
            $jsonObject = (array)$jsonObject;
        }
        if(is_array($jsonObject)){
            foreach($jsonObject as $key=>$value){
                $jsonObject[$key] = YuUtil::json_to_array($value);
            }
        }
        return $jsonObject;
    }

    /**
     * @title 格式化，去空
     * @description 格式化，去空
     * @author Admin ldy
     * @param name:$da  type:string require:1 default:1 desc:
     * @time 2018/9/20  16:51
     * @return string
     */
    public static function format_empty($da){
        return empty($da)?'':$da;
    }


    /**
     * @title 删除一些空格换行之类的
     * @description 删除一些空格换行之类的，格式化后，方便内容的提取
     * @author Admin ldy
     * @param name:$str  type:string require:1 default:1 desc:
     * @time 2018/9/20  15:06
     * @return string：格式化后的内容
     */
    public static function dealHtml($str)
    {
        $str = trim($str); //清除字符串两边的空格
        $str = preg_replace("/\t/","",$str); //使用正则表达式替换内容，如：空格，换行，并将替换为空。
        $str = preg_replace("/\r\n/","",$str);
        $str = preg_replace("/\r/","",$str);
        $str = preg_replace("/\n/","",$str);
        $str = preg_replace("/ /","",$str);
        $str = preg_replace("/  /","",$str);  //匹配html中的空格
        return trim($str); //返回字符串
    }

    /**
     * @title 匹配出各个值
     * @description 匹配出各个值
     * @author Admin ldy
     * @param name:$output  type:string require:1 default:1 desc:抓取的网页内容
     * @time 2018/9/20  14:22
     * @return array:返回一个数组
     */
    public static function get_page_info($output) {
        $page_info = array();
        $page_info['site_title'] = '';
        $page_info['site_description'] = '';
        $page_info['site_keywords'] = '';
        $page_info['friend_link_status'] = 0;
        $page_info['site_claim_status'] = 0;
        $page_info['site_home_size'] = 0;

        if(empty($output)) return $page_info;

        $output=YuUtil::dealHtml($output);
        # Keywords
        preg_match('/<META\s+name=["\']keywords[\'"]\s+content=["\']?([\w\W]*?)["\']/si', $output, $matches);
        if (empty($matches[1])) {
            preg_match('/<META\s+content=["\']([\w\W]*?)["\']\s+name=["\']keywords["\']/si', $output, $matches);
        }
        if (empty($matches[1])) {
            preg_match('/<META\s+http-equiv=["\']keywords["\']\s+content=["\']([\w\W]*?)["\']/si', $output, $matches);
        }
        if (empty($matches[1])) {
            preg_match('/<META\s+content=["\']keywords["\']\s+http-equiv=["\']([\w\W]*?)["\']/si', $output, $matches);
        }
        if (!empty($matches[1])) {
            $page_info['site_keywords'] = $matches[1];
        }

        # Description
        preg_match('/<META\s+name=["\']description["\']\s+content=["\']([\w\W]*?)["\']/si', $output, $matches);
        if (empty($matches[1])) {
            preg_match('/<META\s+content=["\']([\w\W]*?)["\']\s+name=["\']description["\']/si', $output, $matches);
        }
        if (empty($matches[1])) {
            preg_match('/<META\s+http-equiv=["\']description["\']\s+content=["\']([\w\W]*?)["\']/si', $output, $matches);
        }
        if (empty($matches[1])) {
            preg_match('/<META\s+content=["\']description["\']\s+http-equiv=["\']([\w\W]*?)["\']/si', $output, $matches);
        }
        if (!empty($matches[1])) {
            $page_info['site_description'] = $matches[1];
        }

        # Title
        preg_match('/<TITLE>([\w\W]*?)<\/TITLE>/si', $output, $matches);
        if (!empty($matches[1])) {
            $page_info['site_title'] = $matches[1];
        }

        # mimvp-site-verification
        preg_match('/<META\s+name=["\']mimvp-site-verification["\']\s+content=["\']([\w\W]*?)["\']/si', $output, $matches);
        preg_match('/<META\s+name="mimvp-site-verification"\s+content="([\w\W]*?)"/si', $output, $matches);
        if (empty($matches[1])) {
            preg_match('/<META\s+content=["\']([\w\W]*?)["\']\s+name=["\']mimvp-site-verification["\']/si', $output, $matches);
        }
        if (!empty($matches[1])) {
            $page_info['site_claim_status'] = $matches[1];
        }

        # mimvp-friend-link
        if(strstr($output, 'https://proxy.mimvp.com') != "") {
            $page_info['friend_link_status'] = 1;
        }

        $page_info['site_home_size'] = strlen($output);

        return $page_info;
    }


    /**
     * @title 新增url的鉴权、格式化、分析、标准化数据
     * @description 新增url的鉴权、格式化、分析、标准化数据（只是格式化数据，和检查传输数据是否成功，并不会执行数据存储操作）
     * @author Admin ldy
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @time 2018/9/20  15:57
     * @return da:数据数组
     */
    public static function getFormatUrlParams($url,$token=''){
        //新增公共url
        $yy=YuDa::getInstance();
        $error=$yy->getErrorString();
        if (empty($error)){
            $urlString = $yy->handleYudata($url);
        }
        $arr = parse_url($urlString);
        $path  = YuUtil::getStringByKey('path',$arr);
        $query  = YuUtil::getStringByKey('query',$arr);
        $fragment  = YuUtil::getStringByKey('fragment',$arr);
        if (!empty($query)){
            $query = '?'.$query;
        }
        if (!empty($fragment)){
            $fragment = '#'.$fragment;
        }
        $key = md5($urlString);
        $con=array('key'=>$key);
        $arr['key'] = $key;
        $arr['con'] = $con;
        $arr['url_path'] = $path.$query.$fragment;
        $arr['url'] = $urlString;
        $arr['token'] = $token;
        $arr['error'] = $error;
        return json_encode($arr);
    }

    /**
     * @title 远程获取一个url的信息
     * @description 远程获取一个url的信息
     * @author Admin ldy
     * @param name:$url  type:string require:1 default:1 desc:url链接
     * @param name:$timeout  type:int require:1 default:0 desc:
     * @param name:$conntimeout  type:int require:1 default:0 desc:
     * @time 2018/9/20  14:20
     * @return mixed:返回一个数组
     */
    public static function get_siteurl_curlinfo($url, $timeout=5, $conntimeout=3) {
        $ch = curl_init();
        $url_host = explode("/", $url)[2];

        $header = array();
        array_push($header, 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36');
        array_push($header, 'Referer:' . $url);
        array_push($header, 'host:' . $url_host);
        array_push($header, 'accept:  text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
        array_push($header, 'upgrade-insecure-requests:1');

        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);        // HTTP 头中的 "Location: "重定向
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);        // 字符串返回
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    // https请求 不验证证书和hosts
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HEADER, 1);                // 0表示不输出Header，1表示输出
        curl_setopt($ch, CURLOPT_NOBODY, 0);                // 0表示不输出Body，1表示输出
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $conntimeout);     // 尝试连接时等待的秒数。设置为0，则无限等待
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout+5);              // 允许 cURL 函数执行的最长秒数
        curl_setopt($ch, CURLOPT_URL, $url);
        $output = curl_exec($ch);
        $curl_info = curl_getinfo($ch);
        curl_close($ch);

//        $content = file_get_contents($url);
        $content = YuUtil::wp_file_get_contents($url);

        $curl_info['page_info'] = YuUtil::get_page_info($content, $curl_info);
        return $curl_info;
    }

    public static function wp_file_get_contents($url)
    {
        $context = stream_context_create(array(
            'http' => array(
                'timeout' => 10
            )
        )); // 超时时间，单位为秒
        return file_get_contents($url, 0, $context);
    }


    /**
     * 递归实现无限极分类
     * @param $array 分类数据
     * @param $pid 父ID
     * @param $level 分类级别
     * @return $list 分好类的数组 直接遍历即可 $level可以用来遍历缩进
     */
    public static function getTree($array, $pid =0, $level = 0){
        //声明静态数组,避免递归调用时,多次声明导致数组覆盖
        static $list = [];
        foreach ($array as $key => $value){
            //第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
            if ($value['pid'] == $pid){
                //父节点为根节点的节点,级别为0，也就是第一级
                $value['level'] = $level;
                //把数组放到list中
                $list[] = $value;
                //把这个节点从数组中移除,减少后续递归消耗
                unset($array[$key]);
                //开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
                YuUtil::getTree($array, $value['id'], $level+1);
            }
        }
        return $list;
    }

    public static function getParent($array,$id=2,$level=0){
        //声明静态数组,避免递归调用时,多次声明导致数组覆盖
        static $list = [];
        foreach ($array as $key => $value){
            ///$key 0 1 2 3 4 5 6……
            /// $value['id']  $value['pid']  $value['name']
            if ($id == $value['id']){
                //父节点为根节点的节点,级别为0，也就是第一级
                $value['level'] = $level;
                //把数组放到list中
                $list[] = $value;
                //把这个节点从数组中移除,减少后续递归消耗
                unset($array[$key]);
                //开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
                YuUtil::getParent($array, $value['pid'], $level+1);
            }
        }
        return $list;
    }

    public static function is_empty($da){
        if ($da =="null"){
            return true;
        }else if(empty($da)){
            return true;
        }else if(is_null($da)){
            return true;
        }else{
            return false;
        }
    }




}
